package com.adobe.ac.maven.ncss;

/*
 * Copyright 2004-2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import java.io.File;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

/**
 * Check the build if for any Method with a ccn greater than a limit in the source code.
 * 
 * Fails the build if told so.
 * 
 * @author <a href="jeanlaurentATgmail.com">Jean-Laurent de Morlhon</a>
 * 
 * @version $Id$
 * 
 * @goal check
 * @phase verify
 * @execute goal="report"
 */
public class NcssViolationCheckMojo
      extends AbstractMojo
{
   /**
    * Specifies the directory where the XML report will be generated.
    * 
    * @parameter default-value="${project.build.directory}"
    * @required
    */
   // FIXME : same variable, same value in NCSSReportMojo...
   private File xmlOutputDirectory;

   /**
    * Whether to fail the build if the validation check fails.
    * 
    * @parameter default-value="true"
    * @required
    */
   private boolean failOnViolation;

   /**
    * Name of the file holding the xml file generated by JavaNCSS
    * 
    * @parameter default-value="javancss-raw-report.xml"
    * @required
    */
   // FIXME : same variable, same value in NCSSReportMojo...
   private String tempFileName;

   /**
    * CCN Limit, any code with a ccn greater than this number will generate a violation
    * 
    * @parameter default-value="10"
    * @required
    */
   private int ccnLimit;

   /**
    * ncss Limit, any code with a ncss greater than this number will generate a violation
    * 
    * @parameter default-value="100"
    * @required
    */
   private int ncssLimit;

   public void execute() throws MojoExecutionException, MojoFailureException
   {
      final Set< String > ccnViolation = new HashSet< String >();
      final Set< String > ncssViolation = new HashSet< String >();
      final List methodList = loadDocument().selectNodes( "//javancss/functions/function" );
      // Count ccn & ncss violations
      final Iterator nodeIterator = methodList.iterator();
      while ( nodeIterator.hasNext() )
      {
         final Node node = ( Node ) nodeIterator.next();
         // count ccn violation
         final int ccn = Integer.valueOf( node.valueOf( "ccn" ) );
         if ( ccn > ccnLimit )
         {
            ccnViolation.add( node.valueOf( "name" ) );
         }
         // count ncss violation
         final int ncss = Integer.valueOf( node.valueOf( "ncss" ) );
         if ( ncss > ncssLimit )
         {
            ncssViolation.add( node.valueOf( "name" ) );
         }
      }
      // crappy....
      reportViolation( "ccn", ccnViolation, ccnLimit );
      reportViolation( "ncss", ncssViolation, ncssLimit );
   }

   private Document loadDocument() throws MojoFailureException
   {
      // FIXME: Building of File is strangely equivalent to method buildOutputFileName of NcssReportGenerator class...
      final File ncssXmlFile = new File( xmlOutputDirectory + File.separator + tempFileName );
      try
      {
         return new SAXReader().read( ncssXmlFile );
      }
      catch ( DocumentException de )
      {
         throw new MojoFailureException( "Can't read javancss xml output file : " + ncssXmlFile );
      }
   }

   private void reportViolation(
         final String statName, final Set< String > violationSet, final int limit ) throws MojoFailureException
   {
      getLog().debug( statName + " Violation = " + violationSet.size() );
      if ( !violationSet.isEmpty() )
      {
         final String violationString = "Your code has " + violationSet.size() + " method(s) with a " + statName + " greater than " + limit;
         getLog().warn( violationString );
         final Iterator< String > iterator = violationSet.iterator();
         while ( iterator.hasNext() )
         {
            getLog().warn( "    " + ( String ) iterator.next() );
         }
         if ( failOnViolation )
         {
            throw new MojoFailureException( violationString );
         }
      }
   }
}
